package com.eduagent.xwqeduagent.api.OneSentenceReprint.api;

import com.google.gson.Gson;
import lombok.Data;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 训练音频服务
 */
@Service
public class TrainAudioService {

    @Value("${xfyun.appid}")
    private String APPID;

    @Value("${xfyun.apikey}")
    private String APIKEY;

    @Autowired
    private AuthService authService;

    private static final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder().build();
    private static final Gson GSON = new Gson();
    private static final String ADD_AUDIO_URL = "http://opentrain.xfyousheng.com/voice_train/audio/v1/add";
    private static final String SUBMIT_WITH_AUDIO_URL = "http://opentrain.xfyousheng.com/voice_train/task/submitWithAudio";

    /**
     * 添加音频URL到训练任务
     * @param token 鉴权token
     * @param request 添加音频请求
     * @return 添加音频响应
     * @throws Exception 请求异常时抛出
     */
    public AddAudioResponse addAudio(String token, AddAudioRequest request) throws Exception {
        // 验证必填参数
        if (request.getTaskId() == null || request.getTaskId().isEmpty()) {
            throw new IllegalArgumentException("训练任务ID不能为空");
        }
        
        if (request.getAudioUrl() == null || request.getAudioUrl().isEmpty()) {
            throw new IllegalArgumentException("音频URL不能为空");
        }
        
        if (!request.getAudioUrl().startsWith("http://") && !request.getAudioUrl().startsWith("https://")) {
            throw new IllegalArgumentException("音频URL必须以http://或https://开头");
        }
        
        String lowerUrl = request.getAudioUrl().toLowerCase();
        if (!lowerUrl.endsWith(".mp3") && !lowerUrl.endsWith(".wav") 
            && !lowerUrl.endsWith(".m4a") && !lowerUrl.endsWith(".pcm")) {
            throw new IllegalArgumentException("音频URL必须以mp3/wav/m4a/pcm结尾");
        }
        
        // 创建请求体
        Map<String, Object> requestJson = new HashMap<>();
        requestJson.put("taskId", request.getTaskId());
        requestJson.put("audioUrl", request.getAudioUrl());
        requestJson.put("textId", request.getTextId());
        requestJson.put("textSegId", request.getTextSegId());
        
        String body = GSON.toJson(requestJson);
        
        // 设置请求类型和请求体
        MediaType JSON = MediaType.parse("application/json; charset=utf-8");
        RequestBody httpBody = RequestBody.create(JSON, body);

        // 生成签名
        String time = String.valueOf(System.currentTimeMillis());
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(APIKEY);
        stringBuilder.append(time);
        stringBuilder.append(AuthService.to32LowerCase(body.getBytes()));
        String signature = AuthService.to32LowerCase(stringBuilder.toString().getBytes());
        
        // 构建请求
        Request httpRequest = new Request.Builder()
                .url(ADD_AUDIO_URL)
                .method("POST", httpBody)
                .addHeader("X-Sign", signature)
                .addHeader("X-Token", token)
                .addHeader("X-AppId", APPID)
                .addHeader("X-Time", time)
                .build();
        
        // 发送请求并获取响应
        Response response = HTTP_CLIENT.newCall(httpRequest).execute();
        AddAudioResponse audioResponse = GSON.fromJson(response.body().string(), AddAudioResponse.class);
        
        // 检查响应状态
        if (audioResponse.getCode() != 0) {
            throw new RuntimeException("添加音频失败: " + audioResponse.getDesc());
        }
        
        return audioResponse;
    }
    
    /**
     * 提交本地音频文件并直接提交训练任务
     * @param token 鉴权token
     * @param request 提交本地音频请求
     * @return 提交本地音频响应
     * @throws Exception 请求异常时抛出
     */
    public SubmitWithAudioResponse submitWithAudio(String token, SubmitWithAudioRequest request) throws Exception {
        // 验证必填参数
        if (request.getTaskId() == null || request.getTaskId().isEmpty()) {
            throw new IllegalArgumentException("训练任务ID不能为空");
        }
        
        if (request.getAudioFile() == null || request.getAudioFile().isEmpty()) {
            throw new IllegalArgumentException("音频文件不能为空");
        }
        
        // 检查文件格式
        String originalFilename = request.getAudioFile().getOriginalFilename();
        if (originalFilename == null) {
            throw new IllegalArgumentException("无法获取音频文件名");
        }
        
        String lowerFilename = originalFilename.toLowerCase();
        if (!lowerFilename.endsWith(".mp3") && !lowerFilename.endsWith(".wav") 
            && !lowerFilename.endsWith(".m4a") && !lowerFilename.endsWith(".pcm")) {
            throw new IllegalArgumentException("音频文件必须是mp3/wav/m4a/pcm格式");
        }
        
        // 验证文件大小
        if (request.getAudioFile().getSize() > 3 * 1024 * 1024) { // 3MB
            throw new IllegalArgumentException("音频文件大小不能超过3MB");
        }
        
        // 将MultipartFile转换为临时文件
        Path tempFile = createTempFile(request.getAudioFile());
        File audioFile = tempFile.toFile();
        
        try {
            // 构建multipart请求
            MultipartBody.Builder builder = new MultipartBody.Builder()
                .setType(MultipartBody.FORM);
            
            // 添加音频文件
            builder.addFormDataPart("file", audioFile.getName(),
                RequestBody.create(MediaType.parse("multipart/form-data"), audioFile));
            
            // 添加其他参数
            builder.addFormDataPart("taskId", request.getTaskId());
            builder.addFormDataPart("textId", String.valueOf(request.getTextId()));
            builder.addFormDataPart("textSegId", String.valueOf(request.getTextSegId()));
            
            // 添加可选参数
            if (request.getDenoiseSwitch() != null) {
                builder.addFormDataPart("denoiseSwitch", String.valueOf(request.getDenoiseSwitch()));
            }
            
            if (request.getMosRatio() != null) {
                builder.addFormDataPart("mosRatio", String.valueOf(request.getMosRatio()));
            }
            
            RequestBody httpBody = builder.build();
            String body = httpBody.toString(); // 这里body只是用于生成签名
            
            // 生成签名
            String time = String.valueOf(System.currentTimeMillis());
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(APIKEY);
            stringBuilder.append(time);
            stringBuilder.append(AuthService.to32LowerCase(body.getBytes()));
            String signature = AuthService.to32LowerCase(stringBuilder.toString().getBytes());
            
            // 构建请求
            Request httpRequest = new Request.Builder()
                    .url(SUBMIT_WITH_AUDIO_URL)
                    .method("POST", httpBody)
                    .addHeader("X-Sign", signature)
                    .addHeader("X-Token", token)
                    .addHeader("X-AppId", APPID)
                    .addHeader("X-Time", time)
                    .build();
            
            // 发送请求并获取响应
            Response response = HTTP_CLIENT.newCall(httpRequest).execute();
            SubmitWithAudioResponse submitResponse = GSON.fromJson(response.body().string(), SubmitWithAudioResponse.class);
            
            // 检查响应状态
            if (submitResponse.getCode() != 0) {
                throw new RuntimeException("提交本地音频文件并提交训练任务失败: " + submitResponse.getDesc());
            }
            
            return submitResponse;
        } finally {
            // 清理临时文件
            Files.deleteIfExists(tempFile);
        }
    }
    
    /**
     * 将MultipartFile转换为临时文件
     * @param file MultipartFile文件
     * @return 返回临时文件路径
     * @throws Exception 文件处理异常时抛出
     */
    private Path createTempFile(MultipartFile file) throws Exception {
        String originalFilename = file.getOriginalFilename();
        String suffix = originalFilename != null ? 
            originalFilename.substring(originalFilename.lastIndexOf(".")) : ".tmp";
            
        Path tempFile = Paths.get(System.getProperty("java.io.tmpdir"), 
            "audio-" + UUID.randomUUID() + suffix);
            
        Files.write(tempFile, file.getBytes());
        return tempFile;
    }

    /**
     * 添加音频请求类
     */
    @Data
    public static class AddAudioRequest {
        private String taskId;     // 训练任务唯一id
        private String audioUrl;   // 文件上传的url地址
        private Long textId;       // 文本ID, 可使用通用训练文本(textId=5001)
        private Long textSegId;    // 训练样例文本段落ID
    }

    /**
     * 添加音频响应类
     */
    @Data
    public static class AddAudioResponse {
        private String flag;
        private int code;
        private String desc;
        private Object data;  // 通常为null
    }
    
    /**
     * 提交本地音频请求类
     */
    @Data
    public static class SubmitWithAudioRequest {
        private MultipartFile audioFile; // 音频文件
        private String taskId;           // 训练任务唯一id
        private Long textId;             // 文本ID, 可使用通用训练文本(textId=5001)
        private Long textSegId;          // 训练样例文本段落ID
        private Integer denoiseSwitch;   // 降噪开关, 默认0
        private Float mosRatio;          // 范围0.0～5.0，单位0.1，默认0.0
    }
    
    /**
     * 提交本地音频响应类
     */
    @Data
    public static class SubmitWithAudioResponse {
        private String flag;
        private int code;
        private String desc;
        private Object data;  // 通常为null
    }
} 